package futbol.tacticas.concursantes.TacticaMike;

import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import futbol.General;
import futbol.tacticas.Comando;
import futbol.tacticas.ComandoGolpearBola;
import futbol.tacticas.ComandoIrA;
import futbol.tacticas.SituacionJugadores;
import futbol.tacticas.concursantes.Tactica;

public class TacticaMike implements Tactica {

	private int nValores[][] = { { -150, 0, 7 }, // 0
			{ -133, 33, 6 }, // 1
			{ -133, -33, 6 }, // 2,
			{ -100, 66, 6 }, // 3
			{ -100, -66, 6 }, // 4
			{ -77, -33, 6 }, // 5
			{ -77, 33, 6 }, // 6
			{ -44, -66, 6 }, // 7
			{ -44, 0, 6 }, // 8
			{ -44, 66, 6 }, // 9
			{ 15, 0, 7 } }; // 10

	private int adelantoX[][] = { { 0, 0, 0, 0, 10, 10, 10, 10, 10 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 },
			{ 0, 17, 33, 47, 66, 71, 104, 104, 104 }

	};

	private int adelantoY[][] = { { 0, 0, 0, 0, 0 }, { -30, -15, 0, 15, 30 },
			{ -30, -15, 0, 15, 30 }, { -30, -15, 0, 15, 30 },
			{ -30, -15, 0, 15, 30 }, { -30, -15, 0, 15, 30 },
			{ -30, -15, 0, 15, 30 }, { -30, -15, 0, 15, 30 },
			{ -30, -15, 0, 15, 30 }, { -30, -15, 0, 15, 30 },
			{ -30, -15, 0, 15, 30 }, { -30, -15, 0, 15, 30 }

	};

	private int aQuienPuedoPasar[][] = { { 2, 3, 4, 5, 6, 7 },
			{ 2, 3, 4, 5, 6, 7 }, { 2, 3, 4, 5, 6, 7 }, { 5, 6, 7, 8, 9, 10 },
			{ 5, 6, 7, 8, 9, 10 }, { 9, 10 }, { 9, 10 }, { 9, 10 }, { 10 },
			{ 7, 10 }, { 9 } };

	private Point posBalonAnterior = new Point();

	private Point posBalonActual = new Point();

	public String getNombre() {
		return "Mike Team";
	}

	public Color getColor1() {
		return Color.WHITE;
	}

	public Color getColor2() {
		return Color.WHITE;
	}

	public Color getColorNumero() {
		return Color.BLACK;
	}

	public int getFuerza(int n) {
		return nValores[n][2];
	}

	public int getXInicial(int n) {
		return nValores[n][0];
	}

	public int getYInicial(int n) {
		return nValores[n][1];
	}

	public Vector<Comando> getComandos(SituacionJugadores sj) {
		Vector<Comando> comandos = new Vector();
		this.posBalonAnterior = this.posBalonActual;
		this.posBalonActual = sj.getBola();
		this.getComandos(comandos, sj);
		return comandos;
	}

	private void getComandos(Vector<Comando> comandos, SituacionJugadores sj) {
		Point dondeCaeLaBola = this.getDondeCaeraLaBola();
		int[] excluir = { 0, 10 };
		if (dondeCaeLaBola.getY() < 67 && dondeCaeLaBola.getY() > -67) {
			excluir = new int[1];
			excluir[0] = 0;
		}
		int j = sj.getInfoMasCercano(sj.getMisJugadores(), dondeCaeLaBola,
				excluir, false)[0];
		comandos.add(new ComandoIrA(j, dondeCaeLaBola.getX(), dondeCaeLaBola
				.getY()));
		for (int i = 0; i < 11; i++) {
			Point dondeEstoy = sj.getMisJugadores()[i];
			if (i != j
					&& General.getDistancia(dondeEstoy.getX(), dondeEstoy
							.getY(), this.posBalonActual.getX(),
							this.posBalonActual.getY()) > 10) {
				if (i != 0) {
					comandos.add(new ComandoIrA(i, nValores[i][0]
							+ this.getAdelantoX(i), nValores[i][1]
							+ this.getAdelantoY(i)));
				} else {
					Point p = this.getDondeCaeraLaBola();
					if (p.getX() < (-160)) {
						comandos.add(new ComandoIrA(i, -160, p.getY()));
					} else if (p.getX() > -108 && p.getX() < -160
							&& p.getY() > 70 && p.getY() < -70) {
						comandos.add(new ComandoIrA(i, p.getX(), p.getY()));
					} else if (sj.getBola().getY() < 51
							&& sj.getBola().getY() > -51
							&& sj.getBola().getX() < -108) {
						comandos.add(new ComandoIrA(i, sj.getBola().getX(), sj
								.getBola().getY()));
					} else if (sj.getBola().getX() > -35
							&& sj.getBola().getX() < 35) {
						comandos.add(new ComandoIrA(i, nValores[i][0]
								+ this.getAdelantoX(i), sj.getBola().getY()));
					} else {
						comandos.add(new ComandoIrA(i, nValores[i][0]
								+ this.getAdelantoX(i), nValores[i][1]
								+ this.getAdelantoY(i)));
					}
				}
			}
			if (General.getDistancia(dondeEstoy.getX(), dondeEstoy.getY(), 160,
					0) < 126
					&& (i == 10)) {
				comandos.add(this.getTiroAPuerta(i, sj));
			} else if (General.getDistancia(dondeEstoy.getX(), dondeEstoy
					.getY(), 160, 0) < 66
					&& (i == 7 || i == 9)) {
				comandos.add(this.getTiroAPuerta(i, sj));
			} else {
				Comando comando = this.getMejorPase(i, sj);
				if (comando != null) {
					comandos.add(comando);
				}
			}
		}
	}

	private Comando getTiroAPuerta(int i, SituacionJugadores sj) {
		Point dondeEstoy = sj.getMisJugadores()[i];
		Point pointResult = new Point(161, 0);
		double distancia = General.getDistancia(dondeEstoy.getX(), dondeEstoy
				.getY(), 160, 0);
		double ang = General.getAngulo(dondeEstoy.getX(), dondeEstoy.getY(),
				160, 0);
		if (nValores[i][2] == 7 && distancia < 126) {
			double xResult = Math.cos(ang) * 127 + dondeEstoy.getX();
			double yResult = Math.sin(ang) * 127 + dondeEstoy.getY();
			pointResult = new Point((int) xResult, (int) yResult);
		} else if (nValores[i][2] == 6 && distancia < 66) {
			double xResult = Math.cos(ang) * 67 + dondeEstoy.getX();
			double yResult = Math.sin(ang) * 67 + dondeEstoy.getY();
			pointResult = new Point((int) xResult, (int) yResult);
		}
		return new ComandoGolpearBola(i, pointResult.getX(), pointResult.getY());
	}

	private int getAdelantoX(int i) {
		int result = 0;
		Point p = this.getDondeCaeraLaBola();
		if (p.getX() > -160 && p.getX() < -140) {
			result = this.adelantoX[i][0];
		} else if (p.getX() <= -120) {
			result = this.adelantoX[i][1];
		} else if (p.getX() > -120 && p.getX() <= -80) {
			result = this.adelantoX[i][2];
		} else if (p.getX() > -80 && p.getX() <= -40) {
			result = this.adelantoX[i][3];
		} else if (p.getX() > -40 && p.getX() <= 0) {
			result = this.adelantoX[i][4];
		} else if (p.getX() > -0 && p.getX() <= 40) {
			result = this.adelantoX[i][5];
		} else if (p.getX() > 40 && p.getX() <= 80) {
			result = this.adelantoX[i][6];
		} else if (p.getX() > 80 && p.getX() <= 120) {
			result = this.adelantoX[i][7];
		} else if (p.getX() > 120) {
			result = this.adelantoX[i][8];
		}
		return result;
	}

	private int getAdelantoY(int i) {
		int result = 0;
		Point p = this.getDondeCaeraLaBola();
		if (p.getY() < -60) {
			result = this.adelantoY[i][0];
		} else if (p.getY() > -60 && p.getY() <= -30) {
			result = this.adelantoY[i][1];
		} else if (p.getY() > -30 && p.getY() <= 0) {
			result = this.adelantoY[i][2];
		} else if (p.getY() > 0 && p.getY() <= 30) {
			result = this.adelantoY[i][3];
		} else if (p.getY() > 60) {
			result = this.adelantoY[i][4];
		}
		return result;
	}

	private Comando getDespeje(int i, SituacionJugadores sj) {
		int distanciaMax = this.getMaximaDistanciaPase(i) - 10;
		Point dondeEstoy = sj.getMisJugadores()[i];
		Point pResult = null;
		if (sj.getBola().getX() < 80 && this.getAdelantoY(i) > 0) {
			pResult = new Point((int) sj.getMisJugadores()[i].getX() + 70,
					(int) sj.getMisJugadores()[i].getY() + this.getAdelantoY(i)
							* 3);
		} else if (sj.getBola().getX() < 80 && this.getAdelantoY(i) < 0) {
			pResult = new Point((int) sj.getMisJugadores()[i].getX() + 70,
					(int) sj.getMisJugadores()[i].getY() + this.getAdelantoY(i)
							* 3);
		} else if (sj.getBola().getX() < 80 && this.getAdelantoY(i) == 0
				&& (int) sj.getMisJugadores()[i].getY() < 0) {
			pResult = new Point((int) sj.getMisJugadores()[i].getX() + 70,
					(int) sj.getMisJugadores()[i].getY() - 60);
		} else if (sj.getBola().getX() < 80 && this.getAdelantoY(i) == 0
				&& (int) sj.getMisJugadores()[i].getY() > 0) {
			pResult = new Point((int) sj.getMisJugadores()[i].getX() + 70,
					(int) sj.getMisJugadores()[i].getY() + 60);
		} else if (sj.getBola().getY() >= 0) {
			pResult = this.getPuntoCorregido(i, dondeEstoy, new Point((int) (sj
					.getMisJugadores()[10]).getX() + 5, (int) sj
					.getMisJugadores()[10].getY() - 5));
		} else {
			pResult = this.getPuntoCorregido(i, dondeEstoy, new Point((int) (sj
					.getMisJugadores()[10]).getX() + 5, (int) sj
					.getMisJugadores()[10].getY() + 5));
		}

		if (sj.getBola().getX() < 80) {
			double ang = 0;
			List candidatos = new ArrayList();
			do {
				double x = Math.sin(ang) * distanciaMax + dondeEstoy.getX();
				double y = Math.cos(ang) * distanciaMax + dondeEstoy.getY();
				if (x > (dondeEstoy.getX() + 30) && y > -120 && y < 120
						&& x < 160) {
					Point p = new Point((int) x, (int) y);
					int n = this.getJugadoresEnZona(sj, p, 20);
					if (n == 0) {
						candidatos.add(p);
					}
				}
				double xx = Math.sin(-ang) * distanciaMax + dondeEstoy.getX();
				double yy = Math.cos(ang) * distanciaMax + dondeEstoy.getY();
				if (xx > (dondeEstoy.getX() + 30) && yy > -120 && yy < 120
						&& xx < 160) {
					Point p = new Point((int) xx, (int) yy);
					int n = this.getJugadoresEnZona(sj, p, 20);
					if (n == 0) {
						candidatos.add(p);
					}
				}
				ang = ang + 0.01;
			} while (ang < Math.PI);
			if (candidatos.size() > 0) {
				double mejorx = -300;
				for (int j = 0; j < candidatos.size(); j++) {
					if (((Point) candidatos.get(j)).getX() > mejorx) {
						pResult = (Point) candidatos.get(j);
						mejorx = ((Point) candidatos.get(j)).getX();
					}
				}
			}
		}
		return new ComandoGolpearBola(i, pResult.getX(), pResult.getY());
	}

	private Comando getMejorPase(int i, SituacionJugadores sj) {
		Comando result = null;
		int jugadorElegido = -1;
		Point pJugadorElegido = null;
		List candidatos = this.getCandidatos(i, sj);
		if (candidatos.size() > 0) {
			pJugadorElegido = sj.getMisJugadores()[((Integer) candidatos.get(0))
					.intValue()];
			jugadorElegido = ((Integer) candidatos.get(0)).intValue();
			for (int j = 0; j < candidatos.size(); j++) {
				if (pJugadorElegido.getX() <= sj.getMisJugadores()[((Integer) candidatos
						.get(j)).intValue()].getX()) {
					jugadorElegido = ((Integer) candidatos.get(j)).intValue();
					pJugadorElegido = sj.getMisJugadores()[((Integer) candidatos
							.get(j)).intValue()];
				}
			}
			Point pOrigen = sj.getMisJugadores()[i];
			Point pDestino = sj.getMisJugadores()[jugadorElegido];
			if (pDestino.getX() != sj.getBola().getX()
					&& pDestino.getY() != sj.getBola().getY()) {
				Point p = this.getPuntoCorregido(i, pOrigen, pDestino);
				result = new ComandoGolpearBola(i, p.getX(), p.getY());
			} else {
				result = this.getDespeje(i, sj);
			}

		} else {
			result = this.getDespeje(i, sj);
		}
		if (i == 10 && sj.getBola().getX() == 0 && sj.getBola().getY() == 0) {
			result = new ComandoGolpearBola(i, 160, -50);
		}
		return result;

	}

	private List getCandidatos(int i, SituacionJugadores sj) {
		List candidatos = new ArrayList();
		int fuerza = this.nValores[1][2];
		int[] puntosSeguros = { -1, -1, -1 };
		switch (fuerza) {
		case 7:
			puntosSeguros[0] = 126;
			puntosSeguros[1] = 66;
			break;
		case 6:
			puntosSeguros[0] = 66;

			if (i == 8
					&& this.getJugadoresEnZonaDetras(sj,
							sj.getMisJugadores()[10], 33) == 0
					&& this.getJugadoresEnZonaDelante(sj,
							sj.getMisJugadores()[8], 33) == 0
					&& this
							.getJugadoresEnZona(sj, sj.getMisJugadores()[10],
									14) == 0
					&& this.getJugadoresEnZona(sj, sj.getMisJugadores()[8], 15) == 0) {
				puntosSeguros[0] = 15;
			}

			break;
		default:
			break;
		}
		int max = 1;

		if (sj.getBola().getX() > 20) {
			max = 2;
		}

		for (int k = 0; k < puntosSeguros.length; k++) {
			if (puntosSeguros[k] > -1) {

				int maximaDistancia = puntosSeguros[k];
				for (int j = 0; j < this.aQuienPuedoPasar[i].length; j++) {
					Point pJugadorAPasar = sj.getMisJugadores()[this.aQuienPuedoPasar[i][j]];

					int distancia = (int) General.getDistancia(sj
							.getMisJugadores()[i].getX(),
							sj.getMisJugadores()[i].getY(), pJugadorAPasar
									.getX(), pJugadorAPasar.getY());
					int cuantosMeCubren = this.getJugadoresEnZona(sj,
							pJugadorAPasar, 16);
					if (distancia <= (maximaDistancia + 10)
							&& distancia >= (maximaDistancia - 10)
							&& cuantosMeCubren < max) {
						candidatos
								.add(new Integer(this.aQuienPuedoPasar[i][j]));
					} else if (i == 8
							&& this.getJugadoresEnZona(sj,
									sj.getMisJugadores()[10], 35) < 1) {
						candidatos.add(new Integer(10));
					}
				}

			}
		}
		return candidatos;
	}

	private int getJugadoresEnZona(SituacionJugadores sj, Point p, int radio) {
		int result = 0;
		Point[] contrario = sj.getContrario();
		for (int i = 0; i < contrario.length; i++) {
			if (General.getDistancia(contrario[i].getX(), contrario[i].getY(),
					p.getX(), p.getY()) < radio) {
				result++;
			}
		}
		return result;
	}

	private int getJugadoresEnZonaDelante(SituacionJugadores sj, Point p,
			int radio) {
		int result = 0;
		Point[] contrario = sj.getContrario();
		for (int i = 0; i < contrario.length; i++) {
			if (General.getDistancia(contrario[i].getX(), contrario[i].getY(),
					p.getX(), p.getY()) < radio
					&& contrario[i].getX() > p.getX()) {
				result++;
			}
		}
		return result;
	}

	private int getJugadoresEnZonaDetras(SituacionJugadores sj, Point p,
			int radio) {
		int result = 0;
		Point[] contrario = sj.getContrario();
		for (int i = 0; i < contrario.length; i++) {
			if (General.getDistancia(contrario[i].getX(), contrario[i].getY(),
					p.getX(), p.getY()) < radio
					&& contrario[i].getX() < p.getX()) {
				result++;
			}
		}
		return result;
	}

	private Point getDondeCaeraLaBola() {
		Point result = null;
		if (this.posBalonActual.getX() != this.posBalonAnterior.getX()
				&& this.posBalonActual.getY() != this.posBalonAnterior.getY()) {
			double xResult = 0;
			double yResult = 0;
			double n = General.getDistancia(this.posBalonAnterior.getX(),
					this.posBalonAnterior.getY(), this.posBalonActual.getX(),
					this.posBalonActual.getY());
			double ang = General.getAngulo(this.posBalonAnterior.getX(),
					this.posBalonAnterior.getY(), this.posBalonActual.getX(),
					this.posBalonActual.getY());
			int suma = this.calcularSumatorio(15, n);
			xResult = Math.cos(ang) * suma + this.posBalonActual.getX();
			yResult = Math.sin(ang) * suma + this.posBalonActual.getY();
			result = new Point((new Double(xResult)).intValue(), (new Double(
					yResult)).intValue());
		} else {
			result = this.posBalonActual;
		}
		return result;
	}

	private Point getPuntoCorregido(int i, Point pOrigen, Point pDestino) {
		int fuerza = this.nValores[i][2];
		Point result = pDestino;
		double distancia = General.getDistancia(pOrigen.getX(), pOrigen.getY(),
				pDestino.getX(), pDestino.getY());
		double ang = General.getAngulo(pOrigen.getX(), pOrigen.getY(), pDestino
				.getX(), pDestino.getY());
		if (distancia > 56 && distancia < 76) {
			if (fuerza == 7) {
				// golpear con fuerza 6
				double xResult = Math.cos(ang) * 45 + pOrigen.getX();
				double yResult = Math.sin(ang) * 45 + pOrigen.getX();
				pDestino = new Point((int) xResult, (int) yResult);
			}
		} else if (distancia <= 44 && distancia > 5) {
			if (fuerza == 7) {
				// golpear con fuerza 5
				double xResult = Math.cos(ang) * 40 + pOrigen.getX();
				double yResult = Math.sin(ang) * 40 + pOrigen.getX();
				pDestino = new Point((int) xResult, (int) yResult);
			} else if (fuerza == 6) {
				// golpear con fuerza 5
				double xResult = Math.cos(ang) * 45 + pOrigen.getX();
				double yResult = Math.sin(ang) * 45 + pOrigen.getX();
				pDestino = new Point((int) xResult, (int) yResult);

			}
		}
		return result;
	}

	private int getMaximaDistanciaPase(int i) {
		int velocidad = this.nValores[i][2] * 3;
		return this.calcularSumatorio(15, velocidad) + 10;
	}

	private int calcularSumatorio(int nMin, double nMax) {
		int result = nMin;
		for (int i = nMin + 1; i <= nMax; i++) {
			result = result + i;
		}
		return result;
	}

}